/**
 * 
 */
package z.tool.service.wrappedcall;

import java.lang.reflect.Method;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import z.tool.service.ServiceResult;

/**
 * @author auzll@163.com
 */
public final class Caller {
    private static final Log LOG = LogFactory.getLog(Caller.class);
    private ExecutorService executor;
    
    public Caller() {
        this(Executors.newCachedThreadPool());
    }
    
    public Caller(ExecutorService executor) {
        this.executor = executor;
    }
    
    public ServiceResult doCall(Object targetObj, Method targetMethod) {
        return doCall(1, TimeUnit.SECONDS, targetObj, targetMethod, new Object[0]);
    }
    
    public ServiceResult doCall(long timeout, TimeUnit unit, Object targetObj, Method targetMethod) {
        return doCall(timeout, unit, targetObj, targetMethod, new Object[0]);
    }

    public ServiceResult doCall(long timeout, TimeUnit unit, Object targetObj, Method targetMethod, Object... args) {
        CountDownLatch latch = new CountDownLatch(1);
        ServiceResult result = new ServiceResult();
        
        // 用另外的线程去调用targetObj的targetMethod
        executor.execute(new CallRunner(result, latch, targetObj, targetMethod, args));
        
        try {
            if (!latch.await(timeout, unit)) { // 超时
                return new ServiceResult()
                    .success(false)
                    .desc("CountDownLatch.await(timeout, unit) fail, waiting time elapsed before the count reached zero");
            }
        } catch (Exception e) {
            LOG.error("method:doCall", e);
            throw new RuntimeException(e.getMessage());
        }
        
        return result;
    }
}
